{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "initial_id",
   "metadata": {
    "collapsed": true,
    "ExecuteTime": {
     "end_time": "2025-04-19T13:38:42.330709Z",
     "start_time": "2025-04-19T13:38:42.018801Z"
    }
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "from sklearn import datasets\n",
    "from sklearn.model_selection import train_test_split, GridSearchCV, cross_val_score\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "from sklearn.decomposition import PCA\n",
    "from sklearn.feature_selection import SelectKBest, chi2\n",
    "from sklearn.svm import LinearSVC, SVC\n",
    "from sklearn.metrics import accuracy_score, precision_recall_fscore_support, confusion_matrix, classification_report"
   ]
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 模型调优"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "18150717420e4540"
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "D:\\Python data analysis\\anaconda\\Lib\\site-packages\\sklearn\\svm\\_base.py:1249: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.\n",
      "  warnings.warn(\n",
      "D:\\Python data analysis\\anaconda\\Lib\\site-packages\\sklearn\\svm\\_base.py:1249: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.\n",
      "  warnings.warn(\n",
      "D:\\Python data analysis\\anaconda\\Lib\\site-packages\\sklearn\\svm\\_base.py:1249: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.\n",
      "  warnings.warn(\n",
      "D:\\Python data analysis\\anaconda\\Lib\\site-packages\\sklearn\\svm\\_base.py:1249: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.\n",
      "  warnings.warn(\n"
     ]
    },
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001B[31m---------------------------------------------------------------------------\u001B[39m",
      "\u001B[31mKeyboardInterrupt\u001B[39m                         Traceback (most recent call last)",
      "\u001B[36mCell\u001B[39m\u001B[36m \u001B[39m\u001B[32mIn[2]\u001B[39m\u001B[32m, line 15\u001B[39m\n\u001B[32m     13\u001B[39m param_grid = {\u001B[33m'\u001B[39m\u001B[33mC\u001B[39m\u001B[33m'\u001B[39m: [\u001B[32m0.1\u001B[39m, \u001B[32m1\u001B[39m, \u001B[32m10\u001B[39m, \u001B[32m100\u001B[39m]}\n\u001B[32m     14\u001B[39m grid_search = GridSearchCV(LinearSVC(class_weight=\u001B[33m'\u001B[39m\u001B[33mbalanced\u001B[39m\u001B[33m'\u001B[39m, random_state=\u001B[32m42\u001B[39m), param_grid, cv=\u001B[32m5\u001B[39m)\n\u001B[32m---> \u001B[39m\u001B[32m15\u001B[39m grid_search.fit(X_train, y_train)\n\u001B[32m     16\u001B[39m \u001B[38;5;28mprint\u001B[39m(\u001B[33m\"\u001B[39m\u001B[33mBest parameter for C: \u001B[39m\u001B[33m\"\u001B[39m, grid_search.best_params_)\n\u001B[32m     17\u001B[39m best_model = grid_search.best_estimator_\n",
      "\u001B[36mFile \u001B[39m\u001B[32mD:\\Python data analysis\\anaconda\\Lib\\site-packages\\sklearn\\base.py:1389\u001B[39m, in \u001B[36m_fit_context.<locals>.decorator.<locals>.wrapper\u001B[39m\u001B[34m(estimator, *args, **kwargs)\u001B[39m\n\u001B[32m   1382\u001B[39m     estimator._validate_params()\n\u001B[32m   1384\u001B[39m \u001B[38;5;28;01mwith\u001B[39;00m config_context(\n\u001B[32m   1385\u001B[39m     skip_parameter_validation=(\n\u001B[32m   1386\u001B[39m         prefer_skip_nested_validation \u001B[38;5;129;01mor\u001B[39;00m global_skip_validation\n\u001B[32m   1387\u001B[39m     )\n\u001B[32m   1388\u001B[39m ):\n\u001B[32m-> \u001B[39m\u001B[32m1389\u001B[39m     \u001B[38;5;28;01mreturn\u001B[39;00m fit_method(estimator, *args, **kwargs)\n",
      "\u001B[36mFile \u001B[39m\u001B[32mD:\\Python data analysis\\anaconda\\Lib\\site-packages\\sklearn\\model_selection\\_search.py:1024\u001B[39m, in \u001B[36mBaseSearchCV.fit\u001B[39m\u001B[34m(self, X, y, **params)\u001B[39m\n\u001B[32m   1018\u001B[39m     results = \u001B[38;5;28mself\u001B[39m._format_results(\n\u001B[32m   1019\u001B[39m         all_candidate_params, n_splits, all_out, all_more_results\n\u001B[32m   1020\u001B[39m     )\n\u001B[32m   1022\u001B[39m     \u001B[38;5;28;01mreturn\u001B[39;00m results\n\u001B[32m-> \u001B[39m\u001B[32m1024\u001B[39m \u001B[38;5;28mself\u001B[39m._run_search(evaluate_candidates)\n\u001B[32m   1026\u001B[39m \u001B[38;5;66;03m# multimetric is determined here because in the case of a callable\u001B[39;00m\n\u001B[32m   1027\u001B[39m \u001B[38;5;66;03m# self.scoring the return type is only known after calling\u001B[39;00m\n\u001B[32m   1028\u001B[39m first_test_score = all_out[\u001B[32m0\u001B[39m][\u001B[33m\"\u001B[39m\u001B[33mtest_scores\u001B[39m\u001B[33m\"\u001B[39m]\n",
      "\u001B[36mFile \u001B[39m\u001B[32mD:\\Python data analysis\\anaconda\\Lib\\site-packages\\sklearn\\model_selection\\_search.py:1571\u001B[39m, in \u001B[36mGridSearchCV._run_search\u001B[39m\u001B[34m(self, evaluate_candidates)\u001B[39m\n\u001B[32m   1569\u001B[39m \u001B[38;5;28;01mdef\u001B[39;00m \u001B[34m_run_search\u001B[39m(\u001B[38;5;28mself\u001B[39m, evaluate_candidates):\n\u001B[32m   1570\u001B[39m \u001B[38;5;250m    \u001B[39m\u001B[33;03m\"\"\"Search all candidates in param_grid\"\"\"\u001B[39;00m\n\u001B[32m-> \u001B[39m\u001B[32m1571\u001B[39m     evaluate_candidates(ParameterGrid(\u001B[38;5;28mself\u001B[39m.param_grid))\n",
      "\u001B[36mFile \u001B[39m\u001B[32mD:\\Python data analysis\\anaconda\\Lib\\site-packages\\sklearn\\model_selection\\_search.py:970\u001B[39m, in \u001B[36mBaseSearchCV.fit.<locals>.evaluate_candidates\u001B[39m\u001B[34m(candidate_params, cv, more_results)\u001B[39m\n\u001B[32m    962\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28mself\u001B[39m.verbose > \u001B[32m0\u001B[39m:\n\u001B[32m    963\u001B[39m     \u001B[38;5;28mprint\u001B[39m(\n\u001B[32m    964\u001B[39m         \u001B[33m\"\u001B[39m\u001B[33mFitting \u001B[39m\u001B[38;5;132;01m{0}\u001B[39;00m\u001B[33m folds for each of \u001B[39m\u001B[38;5;132;01m{1}\u001B[39;00m\u001B[33m candidates,\u001B[39m\u001B[33m\"\u001B[39m\n\u001B[32m    965\u001B[39m         \u001B[33m\"\u001B[39m\u001B[33m totalling \u001B[39m\u001B[38;5;132;01m{2}\u001B[39;00m\u001B[33m fits\u001B[39m\u001B[33m\"\u001B[39m.format(\n\u001B[32m    966\u001B[39m             n_splits, n_candidates, n_candidates * n_splits\n\u001B[32m    967\u001B[39m         )\n\u001B[32m    968\u001B[39m     )\n\u001B[32m--> \u001B[39m\u001B[32m970\u001B[39m out = parallel(\n\u001B[32m    971\u001B[39m     delayed(_fit_and_score)(\n\u001B[32m    972\u001B[39m         clone(base_estimator),\n\u001B[32m    973\u001B[39m         X,\n\u001B[32m    974\u001B[39m         y,\n\u001B[32m    975\u001B[39m         train=train,\n\u001B[32m    976\u001B[39m         test=test,\n\u001B[32m    977\u001B[39m         parameters=parameters,\n\u001B[32m    978\u001B[39m         split_progress=(split_idx, n_splits),\n\u001B[32m    979\u001B[39m         candidate_progress=(cand_idx, n_candidates),\n\u001B[32m    980\u001B[39m         **fit_and_score_kwargs,\n\u001B[32m    981\u001B[39m     )\n\u001B[32m    982\u001B[39m     \u001B[38;5;28;01mfor\u001B[39;00m (cand_idx, parameters), (split_idx, (train, test)) \u001B[38;5;129;01min\u001B[39;00m product(\n\u001B[32m    983\u001B[39m         \u001B[38;5;28menumerate\u001B[39m(candidate_params),\n\u001B[32m    984\u001B[39m         \u001B[38;5;28menumerate\u001B[39m(cv.split(X, y, **routed_params.splitter.split)),\n\u001B[32m    985\u001B[39m     )\n\u001B[32m    986\u001B[39m )\n\u001B[32m    988\u001B[39m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28mlen\u001B[39m(out) < \u001B[32m1\u001B[39m:\n\u001B[32m    989\u001B[39m     \u001B[38;5;28;01mraise\u001B[39;00m \u001B[38;5;167;01mValueError\u001B[39;00m(\n\u001B[32m    990\u001B[39m         \u001B[33m\"\u001B[39m\u001B[33mNo fits were performed. \u001B[39m\u001B[33m\"\u001B[39m\n\u001B[32m    991\u001B[39m         \u001B[33m\"\u001B[39m\u001B[33mWas the CV iterator empty? \u001B[39m\u001B[33m\"\u001B[39m\n\u001B[32m    992\u001B[39m         \u001B[33m\"\u001B[39m\u001B[33mWere there no candidates?\u001B[39m\u001B[33m\"\u001B[39m\n\u001B[32m    993\u001B[39m     )\n",
      "\u001B[36mFile \u001B[39m\u001B[32mD:\\Python data analysis\\anaconda\\Lib\\site-packages\\sklearn\\utils\\parallel.py:77\u001B[39m, in \u001B[36mParallel.__call__\u001B[39m\u001B[34m(self, iterable)\u001B[39m\n\u001B[32m     72\u001B[39m config = get_config()\n\u001B[32m     73\u001B[39m iterable_with_config = (\n\u001B[32m     74\u001B[39m     (_with_config(delayed_func, config), args, kwargs)\n\u001B[32m     75\u001B[39m     \u001B[38;5;28;01mfor\u001B[39;00m delayed_func, args, kwargs \u001B[38;5;129;01min\u001B[39;00m iterable\n\u001B[32m     76\u001B[39m )\n\u001B[32m---> \u001B[39m\u001B[32m77\u001B[39m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28msuper\u001B[39m().\u001B[34m__call__\u001B[39m(iterable_with_config)\n",
      "\u001B[36mFile \u001B[39m\u001B[32mD:\\Python data analysis\\anaconda\\Lib\\site-packages\\joblib\\parallel.py:1918\u001B[39m, in \u001B[36mParallel.__call__\u001B[39m\u001B[34m(self, iterable)\u001B[39m\n\u001B[32m   1916\u001B[39m     output = \u001B[38;5;28mself\u001B[39m._get_sequential_output(iterable)\n\u001B[32m   1917\u001B[39m     \u001B[38;5;28mnext\u001B[39m(output)\n\u001B[32m-> \u001B[39m\u001B[32m1918\u001B[39m     \u001B[38;5;28;01mreturn\u001B[39;00m output \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28mself\u001B[39m.return_generator \u001B[38;5;28;01melse\u001B[39;00m \u001B[38;5;28mlist\u001B[39m(output)\n\u001B[32m   1920\u001B[39m \u001B[38;5;66;03m# Let's create an ID that uniquely identifies the current call. If the\u001B[39;00m\n\u001B[32m   1921\u001B[39m \u001B[38;5;66;03m# call is interrupted early and that the same instance is immediately\u001B[39;00m\n\u001B[32m   1922\u001B[39m \u001B[38;5;66;03m# re-used, this id will be used to prevent workers that were\u001B[39;00m\n\u001B[32m   1923\u001B[39m \u001B[38;5;66;03m# concurrently finalizing a task from the previous call to run the\u001B[39;00m\n\u001B[32m   1924\u001B[39m \u001B[38;5;66;03m# callback.\u001B[39;00m\n\u001B[32m   1925\u001B[39m \u001B[38;5;28;01mwith\u001B[39;00m \u001B[38;5;28mself\u001B[39m._lock:\n",
      "\u001B[36mFile \u001B[39m\u001B[32mD:\\Python data analysis\\anaconda\\Lib\\site-packages\\joblib\\parallel.py:1847\u001B[39m, in \u001B[36mParallel._get_sequential_output\u001B[39m\u001B[34m(self, iterable)\u001B[39m\n\u001B[32m   1845\u001B[39m \u001B[38;5;28mself\u001B[39m.n_dispatched_batches += \u001B[32m1\u001B[39m\n\u001B[32m   1846\u001B[39m \u001B[38;5;28mself\u001B[39m.n_dispatched_tasks += \u001B[32m1\u001B[39m\n\u001B[32m-> \u001B[39m\u001B[32m1847\u001B[39m res = func(*args, **kwargs)\n\u001B[32m   1848\u001B[39m \u001B[38;5;28mself\u001B[39m.n_completed_tasks += \u001B[32m1\u001B[39m\n\u001B[32m   1849\u001B[39m \u001B[38;5;28mself\u001B[39m.print_progress()\n",
      "\u001B[36mFile \u001B[39m\u001B[32mD:\\Python data analysis\\anaconda\\Lib\\site-packages\\sklearn\\utils\\parallel.py:139\u001B[39m, in \u001B[36m_FuncWrapper.__call__\u001B[39m\u001B[34m(self, *args, **kwargs)\u001B[39m\n\u001B[32m    137\u001B[39m     config = {}\n\u001B[32m    138\u001B[39m \u001B[38;5;28;01mwith\u001B[39;00m config_context(**config):\n\u001B[32m--> \u001B[39m\u001B[32m139\u001B[39m     \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m.function(*args, **kwargs)\n",
      "\u001B[36mFile \u001B[39m\u001B[32mD:\\Python data analysis\\anaconda\\Lib\\site-packages\\sklearn\\model_selection\\_validation.py:866\u001B[39m, in \u001B[36m_fit_and_score\u001B[39m\u001B[34m(estimator, X, y, scorer, train, test, verbose, parameters, fit_params, score_params, return_train_score, return_parameters, return_n_test_samples, return_times, return_estimator, split_progress, candidate_progress, error_score)\u001B[39m\n\u001B[32m    864\u001B[39m         estimator.fit(X_train, **fit_params)\n\u001B[32m    865\u001B[39m     \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[32m--> \u001B[39m\u001B[32m866\u001B[39m         estimator.fit(X_train, y_train, **fit_params)\n\u001B[32m    868\u001B[39m \u001B[38;5;28;01mexcept\u001B[39;00m \u001B[38;5;167;01mException\u001B[39;00m:\n\u001B[32m    869\u001B[39m     \u001B[38;5;66;03m# Note fit time as time until error\u001B[39;00m\n\u001B[32m    870\u001B[39m     fit_time = time.time() - start_time\n",
      "\u001B[36mFile \u001B[39m\u001B[32mD:\\Python data analysis\\anaconda\\Lib\\site-packages\\sklearn\\base.py:1389\u001B[39m, in \u001B[36m_fit_context.<locals>.decorator.<locals>.wrapper\u001B[39m\u001B[34m(estimator, *args, **kwargs)\u001B[39m\n\u001B[32m   1382\u001B[39m     estimator._validate_params()\n\u001B[32m   1384\u001B[39m \u001B[38;5;28;01mwith\u001B[39;00m config_context(\n\u001B[32m   1385\u001B[39m     skip_parameter_validation=(\n\u001B[32m   1386\u001B[39m         prefer_skip_nested_validation \u001B[38;5;129;01mor\u001B[39;00m global_skip_validation\n\u001B[32m   1387\u001B[39m     )\n\u001B[32m   1388\u001B[39m ):\n\u001B[32m-> \u001B[39m\u001B[32m1389\u001B[39m     \u001B[38;5;28;01mreturn\u001B[39;00m fit_method(estimator, *args, **kwargs)\n",
      "\u001B[36mFile \u001B[39m\u001B[32mD:\\Python data analysis\\anaconda\\Lib\\site-packages\\sklearn\\svm\\_classes.py:321\u001B[39m, in \u001B[36mLinearSVC.fit\u001B[39m\u001B[34m(self, X, y, sample_weight)\u001B[39m\n\u001B[32m    315\u001B[39m \u001B[38;5;28mself\u001B[39m.classes_ = np.unique(y)\n\u001B[32m    317\u001B[39m _dual = _validate_dual_parameter(\n\u001B[32m    318\u001B[39m     \u001B[38;5;28mself\u001B[39m.dual, \u001B[38;5;28mself\u001B[39m.loss, \u001B[38;5;28mself\u001B[39m.penalty, \u001B[38;5;28mself\u001B[39m.multi_class, X\n\u001B[32m    319\u001B[39m )\n\u001B[32m--> \u001B[39m\u001B[32m321\u001B[39m \u001B[38;5;28mself\u001B[39m.coef_, \u001B[38;5;28mself\u001B[39m.intercept_, n_iter_ = _fit_liblinear(\n\u001B[32m    322\u001B[39m     X,\n\u001B[32m    323\u001B[39m     y,\n\u001B[32m    324\u001B[39m     \u001B[38;5;28mself\u001B[39m.C,\n\u001B[32m    325\u001B[39m     \u001B[38;5;28mself\u001B[39m.fit_intercept,\n\u001B[32m    326\u001B[39m     \u001B[38;5;28mself\u001B[39m.intercept_scaling,\n\u001B[32m    327\u001B[39m     \u001B[38;5;28mself\u001B[39m.class_weight,\n\u001B[32m    328\u001B[39m     \u001B[38;5;28mself\u001B[39m.penalty,\n\u001B[32m    329\u001B[39m     _dual,\n\u001B[32m    330\u001B[39m     \u001B[38;5;28mself\u001B[39m.verbose,\n\u001B[32m    331\u001B[39m     \u001B[38;5;28mself\u001B[39m.max_iter,\n\u001B[32m    332\u001B[39m     \u001B[38;5;28mself\u001B[39m.tol,\n\u001B[32m    333\u001B[39m     \u001B[38;5;28mself\u001B[39m.random_state,\n\u001B[32m    334\u001B[39m     \u001B[38;5;28mself\u001B[39m.multi_class,\n\u001B[32m    335\u001B[39m     \u001B[38;5;28mself\u001B[39m.loss,\n\u001B[32m    336\u001B[39m     sample_weight=sample_weight,\n\u001B[32m    337\u001B[39m )\n\u001B[32m    338\u001B[39m \u001B[38;5;66;03m# Backward compatibility: _fit_liblinear is used both by LinearSVC/R\u001B[39;00m\n\u001B[32m    339\u001B[39m \u001B[38;5;66;03m# and LogisticRegression but LogisticRegression sets a structured\u001B[39;00m\n\u001B[32m    340\u001B[39m \u001B[38;5;66;03m# `n_iter_` attribute with information about the underlying OvR fits\u001B[39;00m\n\u001B[32m    341\u001B[39m \u001B[38;5;66;03m# while LinearSVC/R only reports the maximum value.\u001B[39;00m\n\u001B[32m    342\u001B[39m \u001B[38;5;28mself\u001B[39m.n_iter_ = n_iter_.max().item()\n",
      "\u001B[36mFile \u001B[39m\u001B[32mD:\\Python data analysis\\anaconda\\Lib\\site-packages\\sklearn\\svm\\_base.py:1229\u001B[39m, in \u001B[36m_fit_liblinear\u001B[39m\u001B[34m(X, y, C, fit_intercept, intercept_scaling, class_weight, penalty, dual, verbose, max_iter, tol, random_state, multi_class, loss, epsilon, sample_weight)\u001B[39m\n\u001B[32m   1226\u001B[39m sample_weight = _check_sample_weight(sample_weight, X, dtype=np.float64)\n\u001B[32m   1228\u001B[39m solver_type = _get_liblinear_solver_type(multi_class, penalty, loss, dual)\n\u001B[32m-> \u001B[39m\u001B[32m1229\u001B[39m raw_coef_, n_iter_ = liblinear.train_wrap(\n\u001B[32m   1230\u001B[39m     X,\n\u001B[32m   1231\u001B[39m     y_ind,\n\u001B[32m   1232\u001B[39m     sp.issparse(X),\n\u001B[32m   1233\u001B[39m     solver_type,\n\u001B[32m   1234\u001B[39m     tol,\n\u001B[32m   1235\u001B[39m     bias,\n\u001B[32m   1236\u001B[39m     C,\n\u001B[32m   1237\u001B[39m     class_weight_,\n\u001B[32m   1238\u001B[39m     max_iter,\n\u001B[32m   1239\u001B[39m     rnd.randint(np.iinfo(\u001B[33m\"\u001B[39m\u001B[33mi\u001B[39m\u001B[33m\"\u001B[39m).max),\n\u001B[32m   1240\u001B[39m     epsilon,\n\u001B[32m   1241\u001B[39m     sample_weight,\n\u001B[32m   1242\u001B[39m )\n\u001B[32m   1243\u001B[39m \u001B[38;5;66;03m# Regarding rnd.randint(..) in the above signature:\u001B[39;00m\n\u001B[32m   1244\u001B[39m \u001B[38;5;66;03m# seed for srand in range [0..INT_MAX); due to limitations in Numpy\u001B[39;00m\n\u001B[32m   1245\u001B[39m \u001B[38;5;66;03m# on 32-bit platforms, we can't get to the UINT_MAX limit that\u001B[39;00m\n\u001B[32m   1246\u001B[39m \u001B[38;5;66;03m# srand supports\u001B[39;00m\n\u001B[32m   1247\u001B[39m n_iter_max = \u001B[38;5;28mmax\u001B[39m(n_iter_)\n",
      "\u001B[31mKeyboardInterrupt\u001B[39m: "
     ]
    }
   ],
   "source": [
    "# 加载MNIST数据集\n",
    "mnist = datasets.fetch_openml('mnist_784', version=1)\n",
    "X, y = mnist.data, mnist.target.astype(np.int8)\n",
    "\n",
    "# 数据标准化\n",
    "scaler = StandardScaler()\n",
    "X_scaled = scaler.fit_transform(X)\n",
    "\n",
    "# 划分训练集和测试集\n",
    "X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)\n",
    "\n",
    "# 1. 调整正则化参数（C）\n",
    "param_grid = {'C': [0.1, 1, 10, 100]}\n",
    "grid_search = GridSearchCV(LinearSVC(class_weight='balanced', random_state=42), param_grid, cv=5)\n",
    "grid_search.fit(X_train, y_train)\n",
    "print(\"Best parameter for C: \", grid_search.best_params_)\n",
    "best_model = grid_search.best_estimator_\n",
    "y_pred = best_model.predict(X_test)\n",
    "print(\"Accuracy with best C:\", accuracy_score(y_test, y_pred))\n",
    "\n",
    "# 2. 使用不同的核函数\n",
    "rbf_model = SVC(kernel='rbf', C=1.0, gamma='scale', class_weight='balanced', random_state=42)\n",
    "rbf_model.fit(X_train, y_train)\n",
    "y_pred_rbf = rbf_model.predict(X_test)\n",
    "print(\"Accuracy with RBF kernel:\", accuracy_score(y_test, y_pred_rbf))\n",
    "\n",
    "# 3. 数据增强（使用PCA）\n",
    "pca = PCA(n_components=0.95)\n",
    "X_train_pca = pca.fit_transform(X_train)\n",
    "X_test_pca = pca.transform(X_test)\n",
    "pca_model = LinearSVC(C=1.0, class_weight='balanced', random_state=42)\n",
    "pca_model.fit(X_train_pca, y_train)\n",
    "y_pred_pca = pca_model.predict(X_test_pca)\n",
    "print(\"Accuracy with PCA:\", accuracy_score(y_test, y_pred_pca))\n",
    "# 4. 特征选择\n",
    "selector = SelectKBest(chi2, k=100)\n",
    "X_train_selected = selector.fit_transform(X_train, y_train)\n",
    "X_test_selected = selector.transform(X_test)\n",
    "selected_model = LinearSVC(C=1.0, class_weight='balanced', random_state=42)\n",
    "selected_model.fit(X_train_selected, y_train)\n",
    "y_pred_selected = selected_model.predict(X_test_selected)\n",
    "print(\"Accuracy with feature selection:\", accuracy_score(y_test, y_pred_selected))\n",
    "\n",
    "# 5. 使用交叉验证\n",
    "scores = cross_val_score(best_model, X_train, y_train, cv=5)\n",
    "print(\"Cross-validation scores:\", scores)\n",
    "print(\"Mean cross-validation score:\", np.mean(scores))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "start_time": "2025-04-19T13:38:51.545304Z"
    }
   },
   "id": "4c638ff71b8f0dc7",
   "execution_count": 2
  },
  {
   "cell_type": "markdown",
   "source": [
    "## SVM模型评估"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "53cbe1bbbcf3871a"
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "# 最终评估\n",
    "# 使用最佳模型进行最终评估\n",
    "y_pred_final = best_model.predict(X_test)\n",
    "accuracy = accuracy_score(y_test, y_pred_final)\n",
    "precision, recall, f1, _ = precision_recall_fscore_support(y_test, y_pred_final, average='weighted')\n",
    "conf_matrix = confusion_matrix(y_test, y_pred_final)\n",
    "class_report = classification_report(y_test, y_pred_final)\n",
    "\n",
    "print(\"\\nFinal Evaluation:\")\n",
    "print(\"Accuracy:\", accuracy)\n",
    "print(\"Precision:\", precision)\n",
    "print(\"Recall:\", recall)\n",
    "print(\"F1-score:\", f1)\n",
    "print(\"Confusion Matrix:\\n\", conf_matrix)\n",
    "print(\"Classification Report:\\n\", class_report)"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "1eea3c11c0ea95b9"
  },
  {
   "cell_type": "markdown",
   "source": [
    "## 使用热度图展示混淆矩阵"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "2b3c49ce4282d4e3"
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "# 使用热度图展示混淆矩阵\n",
    "plt.figure(figsize=(10, 7))\n",
    "sns.heatmap(conf_matrix, annot=True, fmt='d', cmap='Blues')\n",
    "plt.title(\"SVM - Confusion Matrix\")\n",
    "plt.xlabel(\"Predicted Label\")\n",
    "plt.ylabel(\"True Label\")\n",
    "plt.show()"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "8ced75bc684b4831"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
